#pragma once
#include <string>
#include <cstddef> // std::size_t

/*
 在 C++ 中，要使用 ODB 将类声明为持久化类，需要包含 ODB 的核心头文
件，并使用 #pragma db object 指令
 #pragma db object 指示 ODB 编译器将 person 类视为一个持久化类。
*/
#include <odb/core.hxx>
#include <odb/nullable.hxx>
namespace bite_im
{
#pragma db object table("user") // 指示 ODB 编译器将 User 类视为一个持久化类  #pragma db object table("user") 指定表名为user，否则默认为User
    class User
    {
    public:
        User() {}
        // 通过手机号构造用户
        User(const std::string &user_id,
             const std::string &phone)
            : _user_id(user_id), _phone(phone), _nickname(user_id) {}
        // 通过用户昵称构造用户
        User(const std::string &user_id,
             const std::string &nickname,
             const std::string &password)
            : _user_id(user_id), _nickname(nickname), _password(password) {}

        void user_id(const std::string &val) { _user_id = val; }
        std::string user_id() { return _user_id; }

        void nickname(const std::string &val) { _nickname = val; }
        std::string nickname()
        {
            if (!_nickname)
            {
                return std::string();
            }
            return *_nickname;
        }

        void phone(const std::string &val) { _phone = val; }
        std::string phone()
        {
            if (!_phone)
            {
                return std::string();
            }
            return *_phone;
        }

        void password(const std::string &val) { _password = val; }
        std::string password()
        {
            if (!_password)
            {
                return std::string();
            }
            return *_password;
        }

        void avatar_id(const std::string &val) { _avatar_id = val; }
        std::string avatar_id()
        {
            if (!_avatar_id)
            {
                return std::string();
            }
            return *_avatar_id;
        }

        void description(const std::string &val) { _description = val; }
        std::string description()
        {
            if (!_description)
            {
                return std::string();
            }
            return *_description;
        }

    private:
        // 将 odb：：access 类作为 User 类的朋友。
        // 这是使数据库支持代码可访问默认构造函数和数据成员所必需的。
        // 如果类具有公共默认构造函数和公共数据成员或数据成员的公共访问器和修饰符，则不需要友元声明
        friend class odb::access;
        //_id 成员前面的 pragma 告诉 ODB 编译器，以下成员是对象的标识符。auto 说明符指示它是数据库分配的 ID。
#pragma db id auto // 表示 ID 字段将自动生成（通常是数据库中的主键），在哪个上面就是主键
        unsigned long _id;
#pragma db type("varchar(64)") index unique // 设置为索引
        std::string _user_id;
#pragma db type("varchar(64)") index unique
        odb::nullable<std::string> _nickname;    // 用户昵称不一定存在---手机号注册默认没有昵称
        odb::nullable<std::string> _description; // 用户个性签名
        odb::nullable<std::string> _password;    // 用户密码不一定存在---手机号注册默认没有密码
#pragma db type("varchar(64)") index unique
        odb::nullable<std::string> _phone;     // 手机号不一定存在---昵称注册默认没有手机号
        odb::nullable<std::string> _avatar_id; // 用户头像
    };
}
// 完成后，需要使用 odb 编译器将当前所写的代码生成数据库支持代码
// odb -d mysql --generate-query --generate-schema 文件名.hxx

// 如果用到了 boost 库中的接口，则需要使用选项 : --profile boost/datetime

// odb -d mysql --generate-query --generate-schema --profile boost/date-time 文件名.hxx
